package com.flow.module.sys.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.flow.module.process.service.impl.BizApplySimpleServiceImpl;
import com.flow.module.sys.pojo.FlowTask;
import com.flow.module.sys.service.FlowProcessService;
import com.flow.module.sys.service.FlowTaskService;
import com.system.comm.utils.FrameStringUtil;
import com.system.handle.model.ResponseCode;
import com.system.handle.model.ResponseFrame;

/**
 * flow_user的Service
 * @author autoCode
 * @date 2017-12-29 10:12:19
 * @version V1.0.0
 */
@Component
public class FlowTaskServiceImpl implements FlowTaskService {

	private static final Logger LOGGER = LoggerFactory.getLogger(BizApplySimpleServiceImpl.class);
	@Autowired
	private TaskService taskService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private FlowProcessService flowProcessService;
	/*@Autowired
	private ProcessEngineConfiguration processEngineConfiguration;*/


	@Override
	public List<FlowTask> findTask(String candidateUser, String processKey) {
		List<FlowTask> data = new ArrayList<FlowTask>();
		List<Task> list = null;
		if(FrameStringUtil.isNotEmpty(processKey)) {
			//获取指定流程里面的任务数
			list = taskService.createTaskQuery()
					.processDefinitionKey(processKey)
					.taskCandidateUser(candidateUser)
					.list();
		} else {
			//获取所有流程里面的任务数
			list = taskService.createTaskQuery()
					.taskCandidateUser(candidateUser)
					.list();
		}
		//获取会签的任务
		List<Task> assignees = taskService.createTaskQuery().taskAssignee(candidateUser).list();//.taskNameLike("%" + s_name + "%");
		if(assignees.size() > 0) {
			list.addAll(assignees);
		}
		if(list != null) {
			for (Task task : list) {
				FlowTask ft = new FlowTask();
				ft.setId(task.getId());
				ft.setName(task.getName());
				ft.setCreateTime(task.getCreateTime());
				ft.setProcessInstanceId(task.getProcessInstanceId());
				data.add(ft);
			}
		}
		return data;
	}

	@Override
	public ResponseFrame pass(String taskId, Map<String, Object> params) {
		ResponseFrame frame = new ResponseFrame();

		LOGGER.info("开始审批taskId[" + taskId + "]");

		Task task = getByTaskId(taskId);
		if(task == null) {
			frame.setCode(-5);
			frame.setMessage("不存在该任务");
			return frame;
		}
		if(flowProcessService.isSuspend(task.getProcessInstanceId())) {
			frame.setCode(-10);
			frame.setMessage("流程实例已暂停");
			return frame;
		}
		
		params.put("checkType", "pass");
		taskService.complete(taskId, params);
		frame.setSucc();
		return frame;
	}

	@Override
	public ResponseFrame back(String taskId,
			Map<String, Object> params) {
		ResponseFrame frame = new ResponseFrame();
		Task task = getByTaskId(taskId);
		if(task == null) {
			frame.setCode(-5);
			frame.setMessage("不存在该任务");
			return frame;
		}
		if(flowProcessService.isSuspend(task.getProcessInstanceId())) {
			frame.setCode(-10);
			frame.setMessage("流程实例已暂停");
			return frame;
		}
		try {
			Map<String, Object> variables;
			// 取得当前任务
			HistoricTaskInstance currTask = historyService
					.createHistoricTaskInstanceQuery().taskId(taskId)
					.singleResult();
			// 取得流程实例
			ProcessInstance instance = flowProcessService.getByProcessInstanceId(currTask.getProcessInstanceId());
			if (instance == null) {
				//流程已经结束
				frame.setCode(-4);
				frame.setMessage("流程已结束");
				return frame;
			}
			variables = instance.getProcessVariables();

			// 取得流程定义
			ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
					.getDeployedProcessDefinition(currTask
							.getProcessDefinitionId());
			if (definition == null) {
				//流程定义未找到
				frame.setCode(-5);
				frame.setMessage("流程未定义");
				return frame;
			}
			//设置驳回的参数
			variables.put("checkType", "back");

			Iterator<Entry<String, Object>> entryKeyIterator = params.entrySet().iterator();
			while (entryKeyIterator.hasNext()) {
				Entry<String, Object> e = entryKeyIterator.next();
				if(variables.get(e.getKey()) == null) {
					variables.put(e.getKey(), e.getValue());
				}
			}
			// 取得上一步活动
			ActivityImpl currActivity = ((ProcessDefinitionImpl) definition).findActivity(currTask.getTaskDefinitionKey());
			List<PvmTransition> nextTransitionList = currActivity.getIncomingTransitions();
			// 清除当前活动的出口
			List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
			List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
			for (PvmTransition pvmTransition : pvmTransitionList) {
				oriPvmTransitionList.add(pvmTransition);
			}
			pvmTransitionList.clear();

			// 建立新出口
			List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
			for (PvmTransition nextTransition : nextTransitionList) {
				PvmActivity nextActivity = nextTransition.getSource();
				ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition).findActivity(nextActivity.getId());
				TransitionImpl newTransition = currActivity.createOutgoingTransition();
				newTransition.setDestination(nextActivityImpl);
				newTransitions.add(newTransition);
			}
			// 完成任务
			List<Task> tasks = taskService.createTaskQuery()
					.processInstanceId(instance.getId())
					.taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
			for (Task t : tasks) {
				taskService.complete(t.getId(), variables);
				historyService.deleteHistoricTaskInstance(t.getId());
			}
			// 恢复方向
			for (TransitionImpl transitionImpl : newTransitions) {
				currActivity.getOutgoingTransitions().remove(transitionImpl);
			}
			for (PvmTransition pvmTransition : oriPvmTransitionList) {
				pvmTransitionList.add(pvmTransition);
			}

			//成功
			frame.setSucc();
		} catch (Exception e) {
			//失败
			frame.setCode(ResponseCode.FAIL.getCode());
			frame.setMessage(e.getMessage());
			LOGGER.error(e.getMessage(), e);
		}

		return frame;
	}

	@Override
	public Task getByTaskId(String taskId) {
		return taskService.createTaskQuery()
				.taskId(taskId).singleResult();
	}

	@Override
	public List<Task> findByProcessInstanceId(String processInstanceId) {
		List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		return list;
	}

	@Override
	public int getCountByProcessInstanceId(String processInstanceId) {
		return (int) taskService.createTaskQuery().processInstanceId(processInstanceId).count();
	}

	@Override
	public Task getByProcessInstanceId(String processInstanceId) {
		List<Task> list = findByProcessInstanceId(processInstanceId);
		return list.size() > 0 ? list.get(0) : null;
	}

}